Skip to content

fix: check daily if update is due based on UPDATE_INTERVAL - #303

Open
aaronspruit wants to merge 13 commits into
rtuszik:devfrom
aaronspruit:fix-updates
Open

fix: check daily if update is due based on UPDATE_INTERVAL#303
aaronspruit wants to merge 13 commits into
rtuszik:devfrom
aaronspruit:fix-updates

Conversation

@aaronspruit

Copy link
Copy Markdown

Originally updates would only be checked if they need to happen based on the duration of UPDATE_INTERVAL. This means that if the container is restarted, it resets the timer.

This change compares the timestamp on DATA_DIR/.photon-index-updated to the UPDATE_INTERVAL on a daily basis.

I believe this was the originally intended functionality, as by default it means the container needs to be running for 30 days before an update is even attempted...instead of doing updates every UPDATE_INTERVAL.

I was very confused as to why my service hadn't updated when the last time it did so was Feb 17th and UPDATE_INTERVAL=30d (even with bouncing the container). This fix correctly identified that today it's 45 days out of date and did the update.

$ task check
task: [deadcode] uv run vulture --min-confidence 100 --exclude ".venv" .
task: [format] uv run ruff format
task: [lint] uv run ruff check --fix
task: [typecheck] uv run ty check
All checks passed!
17 files left unchanged
All checks passed!

$ task test
task: [test] uv run pytest
================================================= test session starts =================================================
platform linux -- Python 3.13.12, pytest-9.0.2, pluggy-1.6.0
rootdir: /mnt/c/Users/rebel/repos/photon-docker
configfile: pyproject.toml
plugins: cov-7.0.0
collected 36 items                                                                                                    

tests/utils/test_regions.py ...................                                                                 [ 52%]
tests/utils/test_sanitize.py ......                                                                             [ 69%]
tests/utils/test_validate_config.py ...........                                                                 [100%]

================================================= 36 passed in 2.99s ==================================================

@aaronspruit aaronspruit changed the title fix: check if update is due daily based on UPDATE_INTERVAL fix: check daily if update is due based on UPDATE_INTERVAL Apr 3, 2026
@rtuszik

rtuszik commented Apr 4, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR!

This approach is something I have considered initially. Having the schedule reset on container restart is really not ideal.

However, there are some issues with this:

  • A 24 hour polling interval as you have set it in this PR would mean that an actual update timeframe is technically between 24 and 48 hours. Thats the maximum precision this would allow us.

  • An update will be attempted on every poll if the time difference exceeds UPDATE_INTERVAL as set by the user. The marker is only updated after a successful update. If I were to set a 24 hour update interval, it would attempt an update every 24 hours. If the polling frequency was reduced to tackle the precision issue, the frequency of update attempts would increase further.

I'm happy to hear your thoughts on this as I haven't found the right approach here without totally over-engineering this.

@aaronspruit

Copy link
Copy Markdown
Author

Ah, ok, I see what you're trying to avoid. It just wasn't clear from the ENV VAR what was going on - and that the container had to be UP for the complete UPDATE_INTERVAL for it to even trigger.

* A 24 hour polling interval as you have set it in this PR would mean that an actual update timeframe is technically between 24 and 48 hours. Thats the maximum precision this would allow us.

Agreed. If you have the UPDATE_INTERVAL set to anything >1d you lose the precision of WHEN the updates fire within the day window. Unsure that this is a bad thing though (are people updating in less than a day? TBH, based on the guidance you have, I'd say there should be code to make the UPDATE_INTERVAL minimum 7d or larger). To remediate, you could change the thread to sleep for 1, instead of 86400. As the default is 30 days, and I imagine this is because you don't want people hammering the downloads, I figured to check every day would be OK. However, to make it more in-line with your existing code, simple change. Granted, as you point out below, that'd be bad from a retry perspective :)

* An update will be attempted on every poll if the time difference exceeds `UPDATE_INTERVAL` as set by the user. The marker is only updated after a successful update. If I were to set a 24 hour update interval, it would attempt an update every 24 hours. If the polling frequency was reduced to tackle the precision issue, the frequency of update attempts would increase further.

Also agreed. I guess the issue becomes do you want people to artificially lower the UPDATE_INTERVAL to something that makes sense based on restarts after they figure this out - in my case it'd be somewhere <= 7d (ultimately more load on the system happy-path) as I'm running in K8s. Or something like this where errors could cause daily retries daily. Unsure if you have a way to capture how many download issues are happening forcing retries. Anecdotally, I don't have that issue. A way to mitigate would be to do an exponential back-off based on days, that doubles with each failure. That means, if you assume the default of 30 days, you would have 4 additional tries (assuming the container doesn't get restarted, could mitigate with writing the error duration to disk). Could be a decent compromise.

Another mitigation would be around date-versioning the hosted tar and doing a lookup. I have no idea how often the dataset is actually updated on your mirror either, and so I don't know if I change UPDATE_INTERVAL to something <30d, I'm downloading the same stuff each time.

Just some ideas.

@tedpearson

Copy link
Copy Markdown

Mine hadn't updated since February due to this issue. Interested in seeing a fix for this, whether it's this change, a minor change to this approach, or a new approach. Willing to help also.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e77fc9ee-028e-49d6-8d5d-47396339ae01

📥 Commits

Reviewing files that changed from the base of the PR and between 4b89f0c and 6861d3f.

📒 Files selected for processing (7)
  • README.md
  • src/index.py
  • src/process_manager.py
  • src/utils/config.py
  • tests/test_index.py
  • tests/test_process_manager.py
  • tests/utils/test_config.py

📝 Walkthrough

Walkthrough

The process manager now polls every 60 seconds and checks index age before updates. Update attempts use a one-hour backoff. Interval parsing and index-age handling are covered by tests, and the README documents the new behaviour.

Changes

Index-age update polling

Layer / File(s) Summary
Index age and interval contracts
src/index.py, src/utils/config.py, tests/test_index.py, tests/utils/test_config.py
age_seconds() reports index age and clamps future timestamps to zero. parse_interval() converts day, hour, and minute values to seconds and defaults invalid values to one day.
Polling and throttled update flow
src/process_manager.py
Scheduled updates poll every 60 seconds. _is_update_due() checks index age, and _maybe_update() throttles attempts for one hour.
Behaviour validation and documentation
tests/test_process_manager.py, README.md
Tests cover polling, marker age, missing markers, throttling, and retries. The README describes the updated interval behaviour.

Estimated code review effort: 3 (Moderate) | ~25 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarises the main change: daily checks determine whether an update is due from UPDATE_INTERVAL.
Description check ✅ Passed The description explains the scheduling change, its restart-related purpose, retry behaviour, and validation results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1e3ba7a1-1f9e-4433-820e-ca87954d2698

📥 Commits

Reviewing files that changed from the base of the PR and between 2f92523 and 4b89f0c.

📒 Files selected for processing (2)
  • src/process_manager.py
  • tests/test_process_manager.py

Comment thread src/process_manager.py Outdated
Comment on lines +250 to +261
def _parse_interval(self, interval: str) -> datetime.timedelta:
interval = interval.lower()
value = int(interval[:-1])
unit = interval[-1]
if unit == "d":
return datetime.timedelta(days=value)
if unit == "h":
return datetime.timedelta(hours=value)
if unit == "m":
return datetime.timedelta(minutes=value)
logger.warning(f"Invalid UPDATE_INTERVAL format: {interval}, defaulting to 1 day")
return datetime.timedelta(days=1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Handle malformed interval values before conversion.

int(interval[:-1]) raises for values such as "", "d", and "invalid". The fallback at the end of this method is then unreachable. The scheduled job will fail instead of using the stated one-day default.

Catch ValueError and IndexError before reading the unit. Add malformed-value cases to test_parse_interval.

Proposed fix
 def _parse_interval(self, interval: str) -> datetime.timedelta:
     interval = interval.lower()
-    value = int(interval[:-1])
-    unit = interval[-1]
+    try:
+        value = int(interval[:-1])
+        unit = interval[-1]
+    except (ValueError, IndexError):
+        logger.warning(f"Invalid UPDATE_INTERVAL format: {interval}, defaulting to 1 day")
+        return datetime.timedelta(days=1)
     if unit == "d":
         return datetime.timedelta(days=value)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def _parse_interval(self, interval: str) -> datetime.timedelta:
interval = interval.lower()
value = int(interval[:-1])
unit = interval[-1]
if unit == "d":
return datetime.timedelta(days=value)
if unit == "h":
return datetime.timedelta(hours=value)
if unit == "m":
return datetime.timedelta(minutes=value)
logger.warning(f"Invalid UPDATE_INTERVAL format: {interval}, defaulting to 1 day")
return datetime.timedelta(days=1)
def _parse_interval(self, interval: str) -> datetime.timedelta:
interval = interval.lower()
try:
value = int(interval[:-1])
unit = interval[-1]
except (ValueError, IndexError):
logger.warning(f"Invalid UPDATE_INTERVAL format: {interval}, defaulting to 1 day")
return datetime.timedelta(days=1)
if unit == "d":
return datetime.timedelta(days=value)
if unit == "h":
return datetime.timedelta(hours=value)
if unit == "m":
return datetime.timedelta(minutes=value)
logger.warning(f"Invalid UPDATE_INTERVAL format: {interval}, defaulting to 1 day")
return datetime.timedelta(days=1)

Comment thread src/process_manager.py Outdated
@rtuszik

rtuszik commented Aug 8, 2026

Copy link
Copy Markdown
Owner

I apologize for my late response to this.
I've rebased your branch and made some changes to poll more frequently, which should negate the concerns i've had for this.

Let me know if you're happy with me merging this or if you would like to follow up on this.

Thanks for the patience and the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Updates don't seem to work as expected when container is restarted

3 participants